<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:lang="http://www.springframework.org/schema/lang"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
							http://www.springframework.org/schema/beans/spring-beans.xsd
							http://www.springframework.org/schema/aop
							http://www.springframework.org/schema/aop/spring-aop.xsd
							http://www.springframework.org/schema/jee
							http://www.springframework.org/schema/jee/spring-jee.xsd
							http://www.springframework.org/schema/lang
							http://www.springframework.org/schema/lang/spring-lang.xsd
							http://www.springframework.org/schema/context
							http://www.springframework.org/schema/context/spring-context.xsd
							http://www.springframework.org/schema/tx
							http://www.springframework.org/schema/tx/spring-tx.xsd
							http://www.springframework.org/schema/util
							http://www.springframework.org/schema/util/spring-util.xsd
							http://www.springframework.org/schema/mvc
							http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
	<!-- 引入配置文件 -->
	<context:annotation-config />
	<context:component-scan base-package="<#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>.*" />

	<!-- 加载连接数据库的参数配置文件 -->
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
				<!-- <value>classpath:redis.properties</value> -->
			</list>
		</property>
		<property name="ignoreUnresolvablePlaceholders" value="true" />
	</bean>

<#if isMutiDataSource>
<#list dataSourceModelMap?keys as key>
<#if databasePool == "Druid">
    <!-- 阿里 druid 数据库连接池 -->
    <bean id="${key?uncap_first}"
          class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <!-- 数据库基本信息配置 -->
        <property name="driverClassName" value="<#noparse>${</#noparse>${key}.jdbc.driver}" />
        <property name="url" value="<#noparse>${</#noparse>${key}.jdbc.url}" />
        <property name="username" value="<#noparse>${</#noparse>${key}.jdbc.username}" />
        <property name="password" value="<#noparse>${</#noparse>${key}.jdbc.password}" />

        <property name="filters" value="<#noparse>${</#noparse>${key}.jdbc.filters}" />

        <!-- 最大并发连接数 -->
        <property name="maxActive" value="<#noparse>${</#noparse>${key}.jdbc.maxActive}" />

        <!-- 初始化连接数量 -->
        <property name="initialSize" value="<#noparse>${</#noparse>${key}.jdbc.initialSize}" />

        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="<#noparse>${</#noparse>${key}.jdbc.maxWait}" />

        <!-- 最小空闲连接数 -->
        <property name="minIdle" value="<#noparse>${</#noparse>${key}.jdbc.minIdle}" />

        <!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis"
                  value="<#noparse>${</#noparse>${key}.jdbc.timeBetweenEvictionRunsMillis}" />

        <!-- 配置一个连接在池中最小生存的时间，单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis"
                  value="<#noparse>${</#noparse>${key}.jdbc.minEvictableIdleTimeMillis}" />

        <property name="validationQuery"
                  value="<#noparse>${</#noparse>${key}.jdbc.validationQuery}" />
        <property name="testWhileIdle" value="<#noparse>${</#noparse>${key}.jdbc.testWhileIdle}" />
        <property name="testOnBorrow" value="<#noparse>${</#noparse>${key}.jdbc.testOnBorrow}" />
        <property name="testOnReturn" value="<#noparse>${</#noparse>${key}.jdbc.testOnReturn}" />
        <property name="maxOpenPreparedStatements"
                  value="<#noparse>${</#noparse>${key}.jdbc.maxOpenPreparedStatements}" />

        <!-- 超过时间限制是否回收 -->
        <property name="removeAbandoned"
                  value="<#noparse>${</#noparse>${key}.jdbc.removeAbandoned}" />

        <!-- 1800 秒，也就是 30 分钟 -->
        <property name="removeAbandonedTimeout"
                  value="<#noparse>${</#noparse>${key}.jdbc.removeAbandonedTimeout}" />

        <!-- 关闭 abanded 连接时输出错误日志 -->
        <property name="logAbandoned" value="<#noparse>${</#noparse>${key}.jdbc.logAbandoned}" />
    </bean>
    </#if>

    <#if databasePool == "HikariCP">
    <!-- HikariCP 数据库连接池 性能最好 没有之一 -->
    <bean id="${key?uncap_first}" class="com.zaxxer.hikari.HikariDataSource"
          destroy-method="close">
        <property name="driverClassName" value="<#noparse>${</#noparse>${key}.jdbc.driver}"/>
        <property name="jdbcUrl" value="<#noparse>${</#noparse>${key}.jdbc.url}"/>
        <property name="username" value="<#noparse>${</#noparse>${key}.jdbc.username}"/>
        <property name="password" value="<#noparse>${</#noparse>${key}.jdbc.password}"/>
        <!-- 等待连接池分配连接的最大时长（毫秒），超过这个时长还没可用的连接则发生SQLException， 缺省:30秒 -->
        <property name="connectionTimeout" value="<#noparse>${</#noparse>${key}.jdbc.connection-timeout}"/>
        <!-- 一个连接idle状态的最大时长（毫秒），超时则被释放（retired），缺省:10分钟 -->
        <property name="idleTimeout" value="<#noparse>${</#noparse>${key}.jdbc.idle-timeout}"/>
        <!-- 一个连接的生命时长（毫秒），超时而且没被使用则被释放（retired），缺省:30分钟，建议设置比数据库超时时长少30秒，参考MySQL wait_timeout参数（show variables like '%timeout%';） -->
        <property name="maxLifetime" value="<#noparse>${</#noparse>${key}.jdbc.max-lifetime}"/>
        <!-- 连接池中允许的最大连接数。缺省值：10；推荐的公式：-->
        <property name="maximumPoolSize" value="<#noparse>${</#noparse>${key}.jdbc.maximum-pool-size}"/>
        <property name="minimumIdle" value="<#noparse>${</#noparse>${key}.jdbc.minimum-idle}"/>
        <property name="autoCommit" value="<#noparse>${</#noparse>${key}.jdbc.auto-commit}"/>
        <property name="connectionTestQuery" value="<#noparse>${</#noparse>${key}.jdbc.connection-test-query}"/>
        <property name="dataSourceProperties">
            <props>
                <prop key="cachePrepStmts">true</prop>
                <prop key="prepStmtCacheSize">250</prop>
                <prop key="prepStmtCacheSqlLimit">2048</prop>
                <prop key="useServerPrepStmts">true</prop>
            </props>
        </property>
    </bean>
    </#if>
</#list>
<#else>
    <#if databasePool == "Druid">
    <!-- 阿里 druid 数据库连接池 -->
    <bean id="dataSource"
          class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <!-- 数据库基本信息配置 -->
        <property name="driverClassName" value="<#noparse>${</#noparse>jdbc.driver}" />
        <property name="url" value="<#noparse>${</#noparse>jdbc.url}" />
        <property name="username" value="<#noparse>${</#noparse>jdbc.username}" />
        <property name="password" value="<#noparse>${</#noparse>jdbc.password}" />

        <property name="filters" value="<#noparse>${</#noparse>jdbc.filters}" />

        <!-- 最大并发连接数 -->
        <property name="maxActive" value="<#noparse>${</#noparse>jdbc.maxActive}" />

        <!-- 初始化连接数量 -->
        <property name="initialSize" value="<#noparse>${</#noparse>jdbc.initialSize}" />

        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="<#noparse>${</#noparse>jdbc.maxWait}" />

        <!-- 最小空闲连接数 -->
        <property name="minIdle" value="<#noparse>${</#noparse>jdbc.minIdle}" />

        <!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis"
                  value="<#noparse>${</#noparse>jdbc.timeBetweenEvictionRunsMillis}" />

        <!-- 配置一个连接在池中最小生存的时间，单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis"
                  value="<#noparse>${</#noparse>jdbc.minEvictableIdleTimeMillis}" />

        <property name="validationQuery"
                  value="<#noparse>${</#noparse>jdbc.validationQuery}" />
        <property name="testWhileIdle" value="<#noparse>${</#noparse>jdbc.testWhileIdle}" />
        <property name="testOnBorrow" value="<#noparse>${</#noparse>jdbc.testOnBorrow}" />
        <property name="testOnReturn" value="<#noparse>${</#noparse>jdbc.testOnReturn}" />
        <property name="maxOpenPreparedStatements"
                  value="<#noparse>${</#noparse>jdbc.maxOpenPreparedStatements}" />

        <!-- 超过时间限制是否回收 -->
        <property name="removeAbandoned"
                  value="<#noparse>${</#noparse>jdbc.removeAbandoned}" />

        <!-- 1800 秒，也就是 30 分钟 -->
        <property name="removeAbandonedTimeout"
                  value="<#noparse>${</#noparse>jdbc.removeAbandonedTimeout}" />

        <!-- 关闭 abanded 连接时输出错误日志 -->
        <property name="logAbandoned" value="<#noparse>${</#noparse>jdbc.logAbandoned}" />
    </bean>
    </#if>

    <#if databasePool == "HikariCP">
    <!-- HikariCP 数据库连接池 性能最好 没有之一 -->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
          destroy-method="close">
        <property name="driverClassName" value="<#noparse>${</#noparse>jdbc.driver}"/>
        <property name="jdbcUrl" value="<#noparse>${</#noparse>jdbc.url}"/>
        <property name="username" value="<#noparse>${</#noparse>jdbc.username}"/>
        <property name="password" value="<#noparse>${</#noparse>jdbc.password}"/>
        <!-- 等待连接池分配连接的最大时长（毫秒），超过这个时长还没可用的连接则发生SQLException， 缺省:30秒 -->
        <property name="connectionTimeout" value="<#noparse>${</#noparse>jdbc.connection-timeout}"/>
        <!-- 一个连接idle状态的最大时长（毫秒），超时则被释放（retired），缺省:10分钟 -->
        <property name="idleTimeout" value="<#noparse>${</#noparse>jdbc.idle-timeout}"/>
        <!-- 一个连接的生命时长（毫秒），超时而且没被使用则被释放（retired），缺省:30分钟，建议设置比数据库超时时长少30秒，参考MySQL wait_timeout参数（show variables like '%timeout%';） -->
        <property name="maxLifetime" value="<#noparse>${</#noparse>jdbc.max-lifetime}"/>
        <!-- 连接池中允许的最大连接数。缺省值：10；推荐的公式：-->
        <property name="maximumPoolSize" value="<#noparse>${</#noparse>jdbc.maximum-pool-size}"/>
        <property name="minimumIdle" value="<#noparse>${</#noparse>jdbc.minimum-idle}"/>
        <property name="autoCommit" value="<#noparse>${</#noparse>jdbc.auto-commit}"/>
        <property name="connectionTestQuery" value="<#noparse>${</#noparse>jdbc.connection-test-query}"/>
        <property name="dataSourceProperties">
            <props>
                <prop key="cachePrepStmts">true</prop>
                <prop key="prepStmtCacheSize">250</prop>
                <prop key="prepStmtCacheSqlLimit">2048</prop>
                <prop key="useServerPrepStmts">true</prop>
            </props>
        </property>
    </bean>
    </#if>
</#if>

<#if isMutiDataSource>
    <!--动态数据源的配置-->
    <bean id="dynamicDataSource" class="<#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>.config.mutidatasource.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="<#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>.config.mutidatasource.DataSourceType">
            <#list dataSourceModelMap?keys as key>
                <entry value-ref="${key?uncap_first}" key="${key?upper_case}"/>
            </#list>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="${dataSourceName?uncap_first}">
        </property>
    </bean>
</#if>

	<!-- spring和MyBatis完美整合，不需要mybatis的配置映射文件 -->
	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
    <#if isMutiDataSource>
        <property name="dataSource" ref="dynamicDataSource" />
    <#else>
        <property name="dataSource" ref="dataSource" />
    </#if>
		<property name="configLocation" value="classpath:/<#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>/sqlmapper/mybatis-config.xml"/>
		<!-- 自动扫描mapping.xml文件 -->
		<property name="mapperLocations">
			<array>
				<value>classpath*:/<#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>/sqlmapper/*Mapper.xml</value>
			</array>
		</property>
	</bean>

	<!-- DAO接口所在包名，Spring会自动查找其下的类 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="annotationClass"
			value="org.springframework.stereotype.Repository" />
		<property name="basePackage" value="<#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>.dao" />
		<property name="sqlSessionFactoryBeanName"
			value="sqlSessionFactory"/>
	</bean>

	<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <#if isMutiDataSource>
        <property name="dataSource" ref="dynamicDataSource" />
    <#else>
        <property name="dataSource" ref="dataSource" />
    </#if>
	</bean>

	<tx:advice id="advice"
		transaction-manager="transactionManager">
		<tx:attributes>
        <#if isMutiDataSource>
            <tx:method name="*" propagation="REQUIRES_NEW" />
            <tx:method name="select*" propagation="REQUIRES_NEW" read-only="true"/>
            <tx:method name="likeSelect*" propagation="REQUIRES_NEW" read-only="true"/>
        <#else>
            <tx:method name="*" propagation="REQUIRED" />
            <tx:method name="select*" read-only="true"/>
            <tx:method name="likeSelect*" read-only="true"/>
        </#if>
		</tx:attributes>
	</tx:advice>

	<!-- 切入点 -->
	<aop:config>
		<aop:pointcut id="mypoint"
			expression="execution(* <#if isCloudModel>${cloudSysEngName}<#else>${packageName}</#if>.service.impl.*.*(..))"/>
		<aop:advisor advice-ref="advice" pointcut-ref="mypoint"/>
	</aop:config>

</beans>
